home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / hash.com / GENTABLE.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-09-26  |  5.5 KB  |  252 lines

  1. Unit GenTable;   {Generic Hash Table}
  2. {$B-}
  3.         {Guarantee Short-Circuit Boolean evaluation}
  4.  
  5. { Implements a String-keyed Hash Table of Datum Objects }
  6.  
  7. { As currently configured (Compare and UpString NOT used), hashing is     }
  8. { case-sensitive. Using these functions will remove this case-sensitivity,}
  9. { but will slow performance somewhat.  The functions are commented off,   }
  10. { the places where they must be used are marked by comments which all     }
  11. { begin like this: "{SUBST:".                                             }
  12.  
  13.  
  14. INTERFACE
  15.  
  16. Uses GenDatum;
  17.  
  18. Const
  19.   MaxEntry = 17;
  20.  
  21. Type
  22.  
  23.   HPtr      = ^EntryRec;
  24.  
  25.   EntryRec  = Object (Datum)
  26.  
  27.              Key  : String;
  28.              Next : HPtr;
  29. {
  30.   (* Applicable Datum Methods Inherited *)
  31.  
  32.              Procedure Set_Data (Var Input_Data; Size : Word);
  33.              Procedure Get_Data (Var Output_Data; Size : Word);
  34.  
  35.   (* End Applicable Datum Methods *)
  36. }
  37.  
  38.              Procedure Create (TheKey : String);
  39.              Procedure Link (NewRec : EntryRec);
  40.              Procedure Destroy;
  41.  
  42.            End;
  43.  
  44.  
  45.   HTable = Object
  46.  
  47.              Entry : Array[0..MaxEntry-1] of HPtr;
  48.              Used  : Array[0..MaxEntry-1] of Boolean;
  49.  
  50.              Procedure Create (DataSize : Word);
  51.              Procedure Enter (E : EntryRec; Var Duplicate : Boolean);
  52.              Procedure Retrieve (TheKey : String; Var Found : Boolean;
  53.                                  Var E : EntryRec);
  54.              Procedure Destroy;
  55.  
  56.            End;
  57.  
  58.  
  59. IMPLEMENTATION
  60.  
  61. (************************************************************************)
  62.  
  63. Procedure EntryRec.Create (TheKey : String);
  64. Begin
  65.   Datum.Create;
  66.   Next := Nil;
  67.   Key := TheKey
  68. End;
  69.  
  70. Procedure EntryRec.Link (NewRec : EntryRec);
  71. Begin
  72.   New (Next);
  73.   Next^ := NewRec
  74. End;
  75.  
  76. Procedure EntryRec.Destroy;
  77. Begin
  78.   Key := '';
  79.   Datum.Destroy
  80. End;
  81.  
  82. (************************************************************************)
  83.  
  84. Procedure HTable.Create (DataSize : Word);
  85. Var
  86.   I : Word;
  87. Begin
  88.   For I := 0 to MaxEntry-1 do
  89.     Begin
  90.       New (Entry[I]);
  91.       Entry[I]^.Create('');
  92.       Entry[I]^.Next := Nil;
  93.       Entry[I]^.Init (DataSize);
  94.       Used[I] := False
  95.     End
  96. End;
  97.  
  98. {
  99.  
  100. (* Function UpString is only needed to remove case-sensitivity *)
  101.  
  102. Function UpString (Str : String) : String;
  103. Var
  104.   I : Byte;
  105.   S : String;
  106. Begin
  107.   S := '';
  108.   For I := 1 to Length (Str) do S := S + UpCase (Str[I])
  109. End;
  110. }
  111.  
  112. Function Hash (TheString : String) : Word;
  113.  
  114. { Returns a Number in the Range 0..MaxEntry-1 }
  115.  
  116. Var
  117.   Temp : Word;
  118.   I    : Word;
  119.  
  120. {SUBST: Use a temporary variable as follows:
  121.  
  122.   TStr := UpString (TheString);
  123.  
  124.   and then substitute TStr for TheString in remaining code
  125.   for Function Hash.}
  126.  
  127. Begin
  128.   Temp := 0;
  129.   For I := 1 to Length(TheString) do Temp := Temp + (Ord(TheString[I]));
  130.   Hash := Temp MOD (MaxEntry)
  131. End;
  132.  
  133. {
  134.  
  135. (*
  136.    Function Compare is only needed if you can NOT guarantee that all keys
  137.    will be of the same case.
  138.  
  139.    The four places where Compare must be used are commented, starting
  140.    with "{SUBST:"
  141. *)
  142.  
  143. Function Compare (Str1,Str2 : String) : Boolean;
  144. Var
  145.   S1,S2 : String;
  146.   I     : Word;
  147. Begin
  148.   If Length(Str1) <> Length(Str2) Then
  149.     Compare := False
  150.   Else
  151.     Begin
  152.       S1 := UpString (Str1);
  153.       S2 := UpString (Str2);
  154.       Compare := (S1 = S2)
  155.     End
  156. End;
  157.  
  158. }
  159.  
  160. Procedure HTable.Enter (E : EntryRec; Var Duplicate : Boolean);
  161. Var
  162.   Temp  : HPtr;
  163.   Ndex  : Word;
  164.   Done  : Boolean;
  165. Begin
  166.   Duplicate := False;
  167.   Ndex := Hash (E.Key);
  168.   If Not Used[Ndex] Then
  169.     Begin
  170.       Entry[Ndex]^ := E;
  171.       Used[Ndex] := True
  172.     End
  173.   Else
  174.     Begin
  175.       Done := False;
  176.       Temp := Entry[Ndex];
  177.       While Not Done do
  178.         Begin
  179.           If (Temp^.Key = E.Key) Then  {SUBST: Compare (Temp^.Key,E.Key)}
  180.             Begin
  181.               Duplicate := True;
  182.               Done := True
  183.             End
  184.           Else
  185.             Begin
  186.               While Temp^.Next <> Nil do
  187.                 Begin
  188.                   Temp := Temp^.Next;
  189.                   If (Temp^.Key = E.Key) Then Duplicate := True
  190.  
  191.                       {SUBST: Compare (Temp^.Key,E.Key)}
  192.                 End;
  193.               Done := True
  194.             End
  195.         End;
  196.       If Not Duplicate Then Temp^.Link (E)
  197.     End
  198. End;
  199.  
  200. Procedure HTable.Retrieve (TheKey : String; Var Found : Boolean;
  201.                            Var E : EntryRec);
  202. Var
  203.   Temp : HPtr;
  204.   Ndex : Word;
  205.   Done : Boolean;
  206. Begin
  207.   Found := False;
  208.   Ndex := Hash (TheKey);
  209.   If Not Used[Ndex] Then Exit {Found = False}
  210.   Else
  211.     Begin
  212.       Done := False;
  213.       Temp := Entry[Ndex];
  214.       While (Not Done) and (Not (Temp^.Key = TheKey)) do
  215.  
  216.                            {SUBST: Compare (Temp^.Key,E.Key)}
  217.  
  218.         If Temp^.Next = Nil Then Done := True
  219.         Else Temp := Temp^.Next;
  220.       If Not (Temp^.Key = TheKey) Then Exit {Found = False}
  221.  
  222.                           {SUBST: Compare (Temp^.Key,E.Key)}
  223.       Else
  224.         Begin
  225.           E := Temp^;
  226.           Found := True
  227.         End
  228.     End
  229. End;
  230.  
  231. Procedure HTable.Destroy;
  232. Var
  233.   Temp1 : HPtr;
  234.   Temp2 : HPtr;
  235.   Ndex  : Word;
  236. Begin
  237.   For Ndex := 0 to MaxEntry-1 do
  238.     Begin
  239.       While Entry[Ndex] <> Nil do
  240.         Begin
  241.           Temp1 := Entry[Ndex];
  242.           Temp2 := Temp1^.Next;
  243.           Dispose (Temp1);
  244.           Entry[Ndex] := Temp2
  245.         End
  246.     End
  247. End;
  248.  
  249. (************************************************************************)
  250.  
  251. BEGIN
  252. END.